

import os
import json
import logging as logger
import pandas as pd
import time
import requests
from mailmerge import MailMerge
from docx import Document

import win32com.client
import pythoncom
import zipfile

# 导入自建包
import config

class LarkException(Exception):
    def __init__(self, code=0, msg=None):
        self.code = code
        self.msg = msg

    def __str__(self) -> str:
        return "{}:{}".format(self.code, self.msg)

    __repr__ = __str__

def request(method, url, headers, payload={}, data="", params={}):
    response = requests.request(method, url, headers=headers, json=payload,data = data,params=params)
    logger.info("URL: " + url)
    logger.info("X-Tt-Logid: " + response.headers['X-Tt-Logid'])
    logger.info("headers:\n"+json.dumps(headers,indent=2, ensure_ascii=False))
    logger.info("payload:\n"+json.dumps(payload,indent=2, ensure_ascii=False))
    resp = {}
    if response.text[0] == '{':
        resp = response.json()
        logger.info("response:\n"+json.dumps(resp,indent=2, ensure_ascii=False))
    else:
        logger.info("response:\n"+response.text)
    code = resp.get("code", -1)
    if code == -1:
        code = resp.get("StatusCode", -1)
    if code == -1 and response.status_code != 200:
         response.raise_for_status()
    if code != 0:
        raise LarkException(code=code, msg=resp.get("msg", ""))
    return resp

# 列出文件夹下的所有文件
def listdir_file(path,list_name): 
    for file in os.listdir(path):
        file_path = os.path.join(path,file)
        if os.path.isdir(file_path) :
            listdir_file(file_path,list_name)
        else:
            list_name.append(file_path)

# 删除模板的第一行空行，目前无效
def init_template(template_path):
    bkd_template = "BKD - documents template.docx"
    template = os.path.join(template_path,bkd_template)
    with open(template) as f:
        document = Document(f)
        for paragraph in document.paragraphs: 	document.paragraphs.remove(paragraph)
        document.save(template)

def empty_template():
    bkd_template = "BKD - documents template.docx"
    filename = os.path.join(config.TEMPLATE_PATH,bkd_template) 
    return filename

def generate_Header(headerinfo,batch = None):
    bkd_template = "BKD - documents template.docx"
    template = os.path.join(config.TEMPLATE_PATH,bkd_template) 
    document = MailMerge(template)
    document.merge(ProductName = headerinfo["Product Name"],
                    ProductCode = headerinfo["Product Code"],
                    DocumentType = config.DOC_TYPE_DICT[headerinfo['Document type']],
                    MonthYear = headerinfo["Doc date"]
                    )
    if batch == None:
        fname = 'BKD - {} {}.docx'.format(headerinfo["Product Code"],headerinfo['Document type'])
        save_path = set_save_path(headerinfo)
    else:
        fname = 'BKD - {} {} COA.docx'.format(headerinfo["Product Code"],batch)
        save_path = config.COA_PATH
    
    filename = os.path.join(save_path,fname)
    document.write(filename)
    return filename

def validate_product_info(ready = False):
    
    #print("\r",os.getcwd(),end="")
    # information
    df_raw = pd.DataFrame()
    if os.path.isfile(os.path.join(config.TEMPLATE_PATH,'BKD - documents template.docx')):
        ready = True
    else:
        print("!Error,template not fond\n\
              \rCheck if {} exists".format('BKD - documents template.docx'))
    
    if os.path.isfile('./data/product_info.csv'):
        df_raw = pd.read_csv('./data/product_info.csv')
        df_raw = df_raw.loc[:,["Product Code","Product Name","Type","Item","Target","Method"]]
    else:
        print("!Error,Product data not found\n\
              \rCheck if {} exists".format('Product Information.xlsx'))
        ready = False

    return df_raw

def validate_df(df):
    df_validity=[True,True,True]
    file_ready = {"msds":True,"coa":True,"spec":True,"all":False}
    columns = ("Product Code","Product Name","Type","Item","Target","Method")
    types = ("Information","Specification","Annual Test Item","Storage and Packaging")
    saps = ("Packaging","Storage Condition","Shelf Life")
    for i in columns:
        if i in list(df.columns.values) == False:df_validity[0]=False;print("Missing %s column"%i)
    if df_validity[0]==True: 
        print("Column integrity validation passed")
        for i in types:
            if i in list(df["Type"].values) == False:df_validity[1]=False;print("Missing %s in type column"%i)
    else:
        file_ready = {"msds":False,"coa":False,"spec":False,"all":False}

    if df_validity[:2] ==[True,True]:
        #print("ready to generate coa")
        if "Composition" in list(df.loc[df["Type"]=='Information']["Item"].values)==False:
            file_ready["msds"]=False
            print("Missing Composition")
        #else: print("ready to generate MSDS ")
        for i in saps:
            if i in list(df.loc[df["Type"]=='Storage and Packaging']["Item"].values)==False:
                print("Missing %s in Storage and Packaging "%i)
                file_ready["spec"]=False
    if file_ready['coa']==True and file_ready['spec']==True and file_ready['msds']==True:file_ready["all"]=True
    
    return file_ready

def statement_df():
    df = pd.read_csv(os.path.join(config.DATA_PATH,'statement.csv'))
    #df.drop(['Index'],axis=1,inplace=True)
    #df.insert(0, 'Product name', df.pop('Product name'))
    #df.insert(0, 'Product code', df.pop('Product code'))
    
    return df

'''
description: 将单个doc或docx文件转换为pdf
param {str} filename docx文件名
param {*} path 输出路径，默认为空，输入到当前文件夹
param {*} is_visiable 是否显示打开word程序
param {*} type 转换成的文件类型
return {*} pdf文件名
'''
def conver2pdf (filename:str,path:str = None, is_visiable:int = 0,type:int = 17)->str:
    #print("start pdf convert")
    pythoncom.CoInitialize()
    word = win32com.client.DispatchEx("Word.Application")
    word.Visible = is_visiable  # 0后台运行，不显示,1前台运行
    word.DisplayAlerts = 0  # 不警告
    doc = word.Documents.Open(filename) # 打开一个已有的word文档
    if path != None:
        new_filename = os.path.join(path,os.path.split(filename)[-1])
    else:
        new_filename = filename
    doc.SaveAs(filename[:-5], type)  # txt=4, html=10, docx=16， pdf=17
    type_number_serial = [4,10,16,17]
    type_name_serial = ["txt","html","docx","pdf"]
    type_name = "pdf"
    """
    for x,y in zip(type_number_serial,type_name_serial):
        if type == x:
            type_name = y
    """
    doc.Close()
    word.Quit()
    pdf_save_name ="{}.{}".format(new_filename[:-5],type_name)
    print("{}.{}  Conversion Complete! ".format(new_filename[:-5],type_name))
    return pdf_save_name

def doc2pdf_list(doc_file_list:list):
    #print(doc_file_list)
    try:
        start_time = time.perf_counter() 
        doc_list = doc_file_list
        doc_list_print = [f.split("\\")[-1] for f in doc_list ]
        n = len(doc_list)
        for i in range(n):
            print("No.{} : {}".format(i+1,doc_list_print[i]))
        print("Total {} documents need to be converted".format(len(doc_list_print)))
        #os.system("pause")
        for i in range (n):
            print("No.{} : {} is being converted......".format(i+1,doc_list_print[i]))
            #print("No.{} : {} 转换完成".format(i+1,doc_list_print[i]),end = '\r')
            conver2pdf2 (doc_list[i],path = None, is_visiable = 0,type = 17)
        end_time = time.perf_counter()
        dur_time = end_time-start_time
        print("Done! Total convert {} files to pdf files,total time {:.2f}s".format(n,dur_time))
    except:
        print("\a please enter the correct folder path.")

def set_save_path(productinfo:dict):
    save_path = os.path.join(config.SAVE_PATH,productinfo['Product Code']+" "+productinfo['Product Name'])
    #print(save_path)
    if not os.path.exists(save_path):os.makedirs(save_path)
    return save_path

def getZipDir(dirpath,outFullName):
    zip = zipfile.ZipFile(outFullName,'w',zipfile.ZIP_DEFLATED)
    for path,dirnames,filenames in os.walk(dirpath):
        fpath = path.replace(dirpath,'')
        for filename in filenames:
            zip.write(os.path.join(path,filename),os.path.join(fpath,filename))
    zip.close()
    logger.info("{} 压缩完成".format(outFullName))
    return outFullName

def zip_Product_Code(Productcode):
    dirpath = ""
    save_path_list =[x for x in os.listdir(config.SAVE_PATH) if os.path.isdir(os.path.join(config.SAVE_PATH,x))]
    for x in save_path_list:
        if x.startswith(Productcode):
            dirpath = os.path.join(config.SAVE_PATH,x)
            dirname = x
            break
    
    if dirpath != "":
        outFullName = os.path.join(config.SAVE_PATH,'Zip',dirname+".zip")
        getZipDir(dirpath,outFullName)

    return outFullName

if __name__ =='__main__':
    zip_Product_Code("SR0297")
    
